package com.alstudio.core.voip;

import java.util.ArrayList;

import android.os.Handler;
import android.text.TextUtils;

import com.alstudio.app.ALLocalEnv;
import com.alstudio.event.ALEventDeliver;
import com.alstudio.module.ALModuleManager;
import com.alstudio.module.voip.ALVoipEvent;
import com.alstudio.module.voip.ALVoipEventType;
import com.alstudio.module.xmpp.protocol.xmpp.packact.ALMessage;
import com.alstudio.module.xmpp.request.ALUiXmppRequestCreator;
import com.alstudio.ui.module.voip.CallActivity;
import com.alstudio.utils.activity.ALActivityLifeStateCallback;
import com.alstudio.utils.activity.ALActivityManager;
import com.alstudio.utils.formater.time.ALTimeUtils;
import com.alstudio.utils.log.ALLog;
import com.alstudio.view.toast.MyToastUtil;
import com.loovee.imaohu.R;

/**
 * 本地voip电话逻辑管理器。
 * 
 * @author alonso lee
 * 
 */
public class ALVoipCallManager implements ALVoipCallManagerEngin,
		ALActivityLifeStateCallback {

	private static ALVoipCallManager mInstance;

	private ArrayList<ALMessage> chatMsgList = new ArrayList<ALMessage>();

	private ALMessage currentCallSession;

	private CallState callstate = CallState.CALL_HANDUP;
	private CallState lastCallState = callstate;

	private int localTime = 0;

	// 每一分钟提交通话时长到服务器
	private final int UPDATE_CHARGE_TIME = 60 * ALTimeUtils.MINUTE;
	// 第一次提交，必须从第二分钟开始
	private final int FIRST_CHARGE_TIME = 60 * ALTimeUtils.MINUTE * 2;
	// 接听时间只有30S
	private final int ACCEPT_CALL_TIMEOUT = 30 * ALTimeUtils.SECOND;

	private Handler mHandler = new Handler();

	private VoipLocalTimeCallback mCallback;

	private VoipCallIconState mIconState;

	private ALVoipDataBaseManager mDataBaseManager;

	private ALVoipCallNotificationCenter mVoipCallNotificationCenter;

	// 未讀通話記錄
	private int missedCall = 0;

	public static ALVoipCallManager getDefaultALVoipManager() {
		if (mInstance == null) {
			mInstance = new ALVoipCallManager();
		}
		return mInstance;
	}

	public ALVoipCallManager() {
		// TODO Auto-generated constructor stub
		mIconState = new VoipCallIconState();
		mDataBaseManager = new ALVoipDataBaseManager();
		ALEventDeliver.getDefaultAlEventDeliver().register(this);

		mVoipCallNotificationCenter = new ALVoipCallNotificationCenter(
				ALLocalEnv.getLocalEnv(), ALLocalEnv.getLocalEnv()
						.getNotificationCenterManager());
	}

	@Override
	public void addChatMsg(ALMessage msg) {
		chatMsgList.add(msg);
	}

	@Override
	public void clearChatMsg() {
		chatMsgList.clear();
	}

	@Override
	public ArrayList<ALMessage> getChatMsgs() {
		// TODO Auto-generated method stub
		return chatMsgList;
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		// 重置图标状态
		mIconState = new VoipCallIconState();
		// 关闭speaker
		ALLocalEnv.getLocalEnv().getVoipMediaManager().setSpeakerState(false);
		stopCharge();
		stopUpdateLocalTimeTask();
		clearChatMsg();
		currentCallSession = null;
		removeInCallNotification();
		removeOutGoingCallNotification();
		stopCancelAccptTask();
		ALLocalEnv.getLocalEnv().getVoipMediaManager().stopVoipRingtone();

	}

	@Override
	public void setCallSession(ALMessage session) {
		currentCallSession = session;
		// 开启30S定时挂断
		startAutoCancelAccptTask();
	}

	@Override
	public ALMessage getCallSession() {
		return currentCallSession;
	}

	@Override
	public void onCallStateChanged(CallState state, ALMessage msg) {
		// TODO Auto-generated method stub
		String callId = "";
		if (currentCallSession != null) {
			callId = currentCallSession.getMsgId();
		}
		lastCallState = callstate;
		callstate = state;
		switch (state) {
		case CALL_DISCONNECT:
			mDataBaseManager.onCallDisconnected(currentCallSession);
			clear();
			break;
		case CALL_ESTABLISED:
			// 關閉來電鈴聲
			ALLocalEnv.getLocalEnv().getVoipMediaManager().stopVoipRingtone();
			mDataBaseManager.onCallEstablished(currentCallSession);
			startCharge();
			startUpdateLocalTimeTask();
			// showInCallNotification();
			// 取消30S定时挂断
			stopCancelAccptTask();
			break;
		case CALL_HANDUP:
			if (lastCallState == CallState.CALL_ESTABLISED) {
				mDataBaseManager.onCallHandup(currentCallSession);
			} else {
				if (lastCallState == CallState.CALL_INCOMMING) {
					// 打出未接来电通知
					mVoipCallNotificationCenter
							.showMissedCallNotification(currentCallSession);
					ALVoipCallUIEventDispatcher.postVoipCallEvent(
							ALVoipUIEventType.ALVOIP_UI_EVENT_MISSED_CALL,
							currentCallSession.getMsgId());

				}
			}
			clear();
			break;
		case CALL_INCOMMING:
			setCallSession(msg);
			callId = currentCallSession.getMsgId();
			mDataBaseManager.onInCommingCall(currentCallSession);
			ALLocalEnv.getLocalEnv().getVoipMediaManager()
					.playIncommingCallRingtone();
			break;
		case CALL_OUTGOING:
			msg.setDisplayed(true);
			setCallSession(msg);
			callId = currentCallSession.getMsgId();
			mDataBaseManager.onOutGoingCall(currentCallSession);
			break;
		case CALL_REJECT:
			mDataBaseManager.onCallReject(currentCallSession);
			clear();
			break;
		case CALL_INCOMMING_NOTICE:
			// 來電提醒
			mDataBaseManager.onCallNotice(msg);
			if (msg != null) {
				callId = msg.getMsgId();
			}
			// 打出未接来电提醒通知
			mVoipCallNotificationCenter
					.showInCommingCallNoticeNotification(msg);

			break;
		default:
			break;
		}
		ALVoipCallUIEventDispatcher.postVoipCallEvent(callstate, lastCallState,
				callId);
	}

	@Override
	public void onNewCallChatMsgReceived(ALMessage msg) {
		// TODO Auto-generated method stub
		addChatMsg(msg);
		if (!ALActivityManager.getALActivityManager().isAppOnForeground()) {
			showNewCallChatMsgNotification();
		} else {
			if (!ALActivityManager.getALActivityManager().isActivityOnTop(
					CallActivity.class.getSimpleName())) {
				showNewCallChatMsgNotification();
			}
		}
	}

	@Override
	public CallState getCurrentState() {
		// TODO Auto-generated method stub
		return callstate;
	}

	@Override
	public int getLocalTime() {
		// TODO Auto-generated method stub
		return localTime;
	}

	@Override
	public void setVoipLocalCallingTimeCallback(VoipLocalTimeCallback callback) {
		// TODO Auto-generated method stub
		this.mCallback = callback;
	}

	@Override
	public VoipCallIconState getCallIconState() {
		// TODO Auto-generated method stub
		return mIconState;
	}

	@Override
	public void setCallIconState(VoipCallIconState state) {
		// TODO Auto-generated method stub
		mIconState = state;
	}

	@Override
	public void handupCall() {
		// TODO Auto-generated method stub
		ALUiXmppRequestCreator.postALUiXmppHandupCall(currentCallSession
				.getVoipSession());

		if (callstate == CallState.CALL_ESTABLISED) {
			// 停止语音传输
			ALVoipEvent event = new ALVoipEvent();
			event.setEventType(ALVoipEventType.ALVOIP_EVENT_STOP_STREAM_TO_REMOTE_USER);

			ALModuleManager.getDefaultModuleManager().postEventToModuleManager(
					event);
		}
		onCallStateChanged(CallState.CALL_HANDUP, null);
	}

	@Override
	public void rejectCall() {
		// TODO Auto-generated method stub
		ALUiXmppRequestCreator.postALUiXmppRejectCall(currentCallSession
				.getVoipSession());
		onCallStateChanged(CallState.CALL_REJECT, null);

	}

	@Override
	public void showInCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.showInCallNotification(currentCallSession);
	}

	@Override
	public void removeInCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeInCallNotification();
	}

	@Override
	public void showOutGoingCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter
				.showOutGoingCallNotification(currentCallSession);
	}

	@Override
	public void showInCommingCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter
				.showInCommingCallNotification(currentCallSession);
	}

	@Override
	public void showInCommingCallNoticeNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter
				.showInCommingCallNoticeNotification(currentCallSession);
	}

	@Override
	public void removeOutGoingCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeOutGoingCallNotification();
	}

	@Override
	public void removeInCommingCallNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeInCommingCallNotification();
	}

	@Override
	public void removeInCommingCallNoticeNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeInCommingCallNoticeNotification();
	}

	@Override
	public void removeInCommingCallMissedNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeInCommingMissedCallNotification();
	}

	@Override
	public void showNewCallChatMsgNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.showNewCallChatMsgNotification(
				currentCallSession, chatMsgList.size());
		removeInCallNotification();
	}

	@Override
	public void removeNewCallChatMsgNotification() {
		// TODO Auto-generated method stub
		mVoipCallNotificationCenter.removeNewCallChatMsgNotification();

	}

	@Override
	public int getMissedCallCount() {
		// TODO Auto-generated method stub
		return missedCall;
	}

	@Override
	public void resetMissedCallCount() {
		// TODO Auto-generated method stub
		missedCall = 0;
	}

	@Override
	public void missedCallCountIncreament() {
		// TODO Auto-generated method stub
		missedCall++;
	}

	@Override
	public void updateCallUserFriendShipState(final String jid,
			final boolean isFriend) {
		// TODO Auto-generated method stub

		if (ALLocalEnv.getLocalEnv().getDatabase()
				.updateCallUserFriendShip(jid, isFriend)) {
			// 更新成功,开始通知界面重新刷新
			ALVoipCallUIEventDispatcher
					.postVoipCallEvent(ALVoipUIEventType.ALVOIP_UI_EVENT_FORCE_REFRESH_CALL_HISTORY);
		}
	}

	@Override
	public void forceFinishCall() {
		// TODO Auto-generated method stub
		switch (callstate) {
		case CALL_INCOMMING:
			rejectCall();
			if (mCallback != null) {
				mCallback.onAcceptTimeout();
			}
			break;
		case CALL_ESTABLISED:
		case CALL_OUTGOING:
			handupCall();
			if (mCallback != null) {
				mCallback.onAcceptTimeout();
			}
			break;
		default:
			break;

		}
	}

	/********************************** 每分钟更新通话时间到服务器 *************************************/
	private Runnable chargingTask = new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			if (currentCallSession != null
					&& !TextUtils.isEmpty(currentCallSession.getVoipSession())) {
				ALUiXmppRequestCreator
						.postALUiXmppVoipCharge(currentCallSession
								.getVoipSession());
				mHandler.postDelayed(this, UPDATE_CHARGE_TIME);
			}
		}
	};

	private void startCharge() {
		mHandler.postDelayed(chargingTask, FIRST_CHARGE_TIME);
	}

	private void stopCharge() {
		mHandler.removeCallbacks(chargingTask);
	}

	/********************************** 每1S更新本地通话时间 *************************************/
	private Runnable updateLocalTimeTask = new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			localTime++;
			mHandler.postDelayed(this, ALTimeUtils.SECOND);
			// 更新时间到数据库
			mDataBaseManager.onUpdateCallingTime(currentCallSession, localTime);
			if (mCallback != null) {
				mCallback.onTimeChanged(localTime);
			}
		}
	};

	private void startUpdateLocalTimeTask() {
		localTime = 0;
		mHandler.postDelayed(updateLocalTimeTask, ALTimeUtils.SECOND);
	}

	private void stopUpdateLocalTimeTask() {
		localTime = 0;
		mHandler.removeCallbacks(updateLocalTimeTask);
	}

	/************************************ 接听时间限制为30S *************************************************/
	private Runnable cancelAcceptTask = new Runnable() {

		@Override
		public void run() {
			// TODO Auto-generated method stub
			onCancelAcceptTimeout();
		}
	};

	private void startAutoCancelAccptTask() {
		mHandler.postDelayed(cancelAcceptTask, ACCEPT_CALL_TIMEOUT);
	}

	private void stopCancelAccptTask() {
		mHandler.removeCallbacks(cancelAcceptTask);
	}

	private void onCancelAcceptTimeout() {
		if (currentCallSession != null) {
			ALMessage tmpCall = new ALMessage();
			tmpCall.setMsgId(currentCallSession.getMsgId());
			if (currentCallSession.getType() == ALMessage.NEW_INCOMMING_CALL) {
				// 来电，拒绝
				rejectCall();
				// 未接來電++
				missedCall++;
				// 新未接来电
				ALVoipCallUIEventDispatcher.postVoipCallEvent(
						ALVoipUIEventType.ALVOIP_UI_EVENT_MISSED_CALL,
						tmpCall.getMsgId());
			} else {
				// 去电，挂断
				handupCall();
				MyToastUtil.getInstance().showCenterToastOnCenter(
						R.string.TxtOutGoingCallTimeoutHint);
				// ALVoipCallUIEventDispatcher
				// .postVoipCallEvent(ALVoipUIEventType.ALVOIP_UI_EVENT_HANDUP_CALL);
			}
			if (mCallback != null) {
				mCallback.onAcceptTimeout();
			}
			// 更新为超时未接通
			mDataBaseManager.onCallTimeout(tmpCall);
		}
	}

	/*************************************** 通知管理 *********************************************/
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.alstudio.utils.activity.ALActivityLifeStateCallback#onALEvent(boolean
	 * )
	 */
	@Override
	public void onALEvent(Boolean isAppOnForeground) {
		// TODO Auto-generated method stub
		ALLog.d("现在在前台吗?" + isAppOnForeground);
		if (isAppOnForeground) {
			// 还在前台
		} else {
			// 在後臺了
			invokeAppToBackGround();
		}
	}

	private void invokeAppToBackGround() {

		switch (callstate) {
		case CALL_ESTABLISED:
			showInCallNotification();
			break;
		case CALL_INCOMMING:
			showInCommingCallNotification();
			break;
		case CALL_INCOMMING_NOTICE:
			showInCommingCallNoticeNotification();
			break;
		case CALL_OUTGOING:
			showOutGoingCallNotification();
			break;
		default:
			break;
		}
	}

}
